#include "iostream"
#include "cstring"
#include "array"

#include "boost/asio/io_context.hpp"
#include "boost/asio/connect.hpp"
#include "boost/asio/ip/tcp.hpp"
#include "boost/asio/write.hpp"
#include "boost/asio/read.hpp"


using boost::asio::ip::tcp;

const int BUF_SIZE = 1024;

int main(int argc, char** argv){
    if(argc != 3){
        std::cerr<<"Usage: "<<argv[0]<<" <host> <port>"<<std::endl;
        return 1;
    }

    const char* host = argv[1];
    const char* port = argv[2];

    boost::asio::io_context io_context;

    try{
        tcp::resolver resolver(io_context);

        auto endpoints = resolver.resolve(tcp::v4(), host, port);

        tcp::socket socket(io_context);
        boost::asio::connect(socket, endpoints);

        char request[BUF_SIZE];
        std::size_t request_length = 0;
        do{
            std::cout<<"Enter message: ";
            std::cin.getline(request, BUF_SIZE);
            request_length = std::strlen(request);
        }while(request_length == 0);

        std::cout<<"---: "<<request<<std::endl;

        boost::asio::write(socket, boost::asio::buffer(request, request_length));

        std::cout<<"Reply is: ";


        std::size_t total_reply_length = 0;
        while(true){
            std::array<char, BUF_SIZE> reply;
            std::size_t reply_length = socket.read_some(boost::asio::buffer(reply));

            std::cout.write(reply.data(), reply_length);

            total_reply_length += reply_length;
            if(total_reply_length >= request_length){
                break;
            }
        }
    }catch(const std::exception& e){
        std::cerr<<e.what()<<std::endl;
    }

    return 0;
}
